#pragma once
#include <stdarg.h>
#include <string>
#include <map>
#include <utility>
#include <sstream>


//http://blog.csdn.net/yuzhihui_no1/article/details/43734663
constexpr int kLogBufferLen = 2048;
static std::string cformat(const std::string &format, ...) {
    char buf[kLogBufferLen] = {0};
    va_list list;
    va_start(list, format);
    vsnprintf(buf, kLogBufferLen, format.c_str(), list);
    va_end(list);
    fflush(stderr);
    return std::string(buf);
}



template<class T>
void print_args(std::stringstream &ss, const T &t) {
    ss<<t;
}

template<class T,class... Args>
void print_args(std::stringstream &ss, const T &t, Args&&... rest) {
    ss<<t<<" ";
    print_args(ss, rest...);
}

template<class... Args>
std::string format(Args&&... rest) {
    std::stringstream ss;
    print_args(ss, std::forward<Args>(rest)...);
    return ss.str();
}

using Fm = std::map<std::string, std::string>;
std::string operator % (const std::string &format, const Fm &rep) {
    std::string ret = format;
    for (const auto &item : rep) {
        while(true) {
            auto key = "{" + item.first + "}";
            auto begin = ret.find(key);
            if (begin == std::string::npos) {
                break;
            }
            ret.replace(begin, key.size(), item.second);
        }
    }
    return ret;
}

using Fs = std::vector<std::string>;
std::string operator % (const std::string &format, const Fs &rep) {
    std::string ret = format;
    for (size_t i = 0; i < rep.size(); i++) {
        while(true) {
            auto key = "{" + std::to_string(i + 1) + "}";
            auto begin = ret.find(key);
            if (begin == std::string::npos) {
                break;
            }
            ret.replace(begin, key.size(), rep[i]);
        }
    }
    return ret;
}
